package sprint2;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Serializable;
import java.lang.Math;
import java.util.InputMismatchException;
import java.util.Scanner;

import sprint2.Enemy;
import sprint2.Character;

/**
 *
 * @author Michael de Kaste
 * @author Refactor door Vincent van Andel
 *
 */
public class BattleSystem  implements Serializable {
	private String hpBalkmax = "||||||||||||||||||||||||||||||||||||||||||||||||||"; //Hoe de HP balk eruitziet als hij vol is.
	private String hpBalkmin = "                                                  "; //Hoe de HP balk eruitziet als hij leeg is.

	private boolean adrenalineRush;
	private double hpMaxME;
	private double hpNowME;
	private double armourME;
	private double powerME;
	private double hitratingME;
	private double dodgeratingME;
	private int speedME;
	private String hpStringME = hpBalkmax.substring(0,(int) (50 * hpNowME / hpMaxME))+ hpBalkmin.substring(0, (50 - (int) (50 * hpNowME / hpMaxME))); // berekenen hoe de huidige balk eruitziet.
	private double critChanceME;
	private double critDamageME;

	private double hpMaxHE;
	private double hpNowHE;
	private double armourHE;
	private double powerHE;
	private double hitratingHE;
	private double dodgeratingHE;
	private int speedHE;
	private String hpStringHE = hpBalkmax.substring(0,(int) (50 * hpNowHE / hpMaxHE))+ hpBalkmin.substring(0, (50 - (int) (50 * hpNowHE / hpMaxHE))); // berekenen hoe zijn huidige balk eruitziet.
	private double critChanceHE;
	private double critDamageHE;

	Scanner scanner = new Scanner(System.in);

	/**
	 * de constructor van battlesystem.
	 * de waardes van Character worden meegegeven aan de constructor evenals de waardes van een Enemy.
	 * vervolgens worden de juiste setter aangeroepen om ze te gebruiken.
	 * ME achter iets staat voor jijzelf.
	 * HE achter iets staat voor de vijand.
	 */
	public BattleSystem(Enemy enemy, Character character) {
		setAdrenalineRush(true);
		setHpMaxHE(enemy.getHpMax());
		setHpNowHE(hpMaxHE);
		setArmourHE(enemy.getArmour());
		setPowerHE(enemy.getPower());
		setHitratingHE(enemy.getHitrating());
		setDodgeratingHE(enemy.getDodgerating());
		setSpeedHE(enemy.getSpeed());
		setCritChanceHE(enemy.getCritChance());
		setCritDamageHE(enemy.getCritDamage());
		setHpMaxME(character.getHpMax());
		setHpNowME(character.getHpNow());
		setArmourME(character.getArmour());
		setPowerME(character.getPower());
		setHitratingME((character.getHitrating()));
		setDodgeratingME((character.getDodgerating()));
		setSpeedME(character.getSpeed());
		setCritDamageME(character.getCritDamage());
		setCritChanceME(character.getCritChance());
		hpStringHE = hpBalkmax.substring(0, (int) (50 * hpNowHE / hpMaxHE))
				+ hpBalkmin.substring(0, (50 - (int) (50 * hpNowHE / hpMaxHE)));
		hpStringME = hpBalkmax.substring(0, (int) (50 * hpNowME / hpMaxME))
				+ hpBalkmin.substring(0, (50 - (int) (50 * hpNowME / hpMaxME)));

	}

	/**
	 * 
	 * 
	 * @param filename
	 * output een opgegeven bestand	
	 */

	static void printOut(String filename) {
		BufferedReader in = null;
		try {
			File file = new File(filename);
			in = new BufferedReader(new FileReader(file));
		} catch (FileNotFoundException e) {
			System.out.println("The file doesn't exist.");
			System.exit(0);
		} catch (IOException e) {
			System.out.println("I/O Error");
			System.exit(0);
		}
		try {
			while (in.ready()) {
				System.out.println(in.readLine());
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	/**
	 * 
	 * 
	 * @param fileenemy
	 * 
	 * een standaard beurt in een gevecht. waarbij jij aan de beurt bent.
	 * 
	 */
	public void fightME(String fileenemy) {
		printOut(fileenemy);
		System.out.println("Je probeert te aanvallen..."); // begin output prompt
		int hitrating = (int) (100 * Math.random() + 1);
		int dodgerating = (int) (100 * Math.random() + 1);
		double varietyDamage =(((1-Math.random())*(powerME/5))-(powerME/10));
		System.out.println((hitrating < hitratingME || dodgerating > dodgeratingHE) ? "Raak!": "Mis!"); // output "Raak!" bij true, "Mis!" bij false
		if (hitrating < hitratingME || dodgerating > dodgeratingHE) { // Als je raak gooit...
			double damage = ((powerME + varietyDamage) * (((100 * Math.random() + 1) <= critChanceME) ? critDamageME  : 1) * (1 - (armourHE / 100)));
			hpNowHE -= damage; // de kracht van je aanval wordt eerst tegengehouden door
															// wat armour en vervolgens gaat dat van zijn hp af.
			hpNowHE = ((hpNowHE > 0) ? hpNowHE : 0.0); // zijn hp is een double bij groter dan 0, anders wordt de waarde
														// 0.
			hpStringHE = hpBalkmax.substring(0, (int) (50 * hpNowHE / hpMaxHE))
					+ hpBalkmin.substring(0,
							(50 - (int) (50 * hpNowHE / hpMaxHE)));
			System.out
					.println("Je aanval deed "
							+ Math.round(damage)
							+ " schade!"); // output de schade
		}
		System.out.println("1: ga verder!");
		scanner.next();
	}

	/**
	 * 
	 * 
	 * @param fileenemy
	 * 
	 * een standaard beurt in een gevecht. waarbij hij aan de beurt is.
	 * 
	 */

	public void fightHE(String fileenemy) {
		printOut(fileenemy);
		System.out.println("Hij probeert te aanvallen...");
		int hitrating = (int) (100 * Math.random() + 1);
		int dodgerating = (int) (100 * Math.random() + 1);
		double varietyDamage = (((1-Math.random())*(powerHE/5))-(powerHE/10));
		System.out
				.println((hitrating < hitratingHE || dodgerating > dodgeratingME) ? "Raak!"
						: "Mis!"); // output "Raak!" bij true, "Mis!" bij false
		if (hitrating < hitratingHE || dodgerating > dodgeratingME) { // Als je raak gooit...
			double damage = ((powerHE + varietyDamage)
					* (((100 * Math.random() + 1) <= critChanceHE) ? critDamageHE
							: 1) * (1 - (armourME / 100)));
			hpNowME -= damage;
			hpNowME = ((hpNowME > 0) ? hpNowME : 0.0);
			hpStringME = hpBalkmax.substring(0, (int) (50 * hpNowME / hpMaxME))
					+ hpBalkmin.substring(0,
							(50 - (int) (50 * hpNowME / hpMaxME)));
			System.out
					.println("zijn aanval deed "
							+ Math.round(damage)
							+ " schade!");
		}
		System.out.println("1: ga verder!");
		scanner.next();
	}

	/**
	 * 
	 * @param character
	 * @param fileenemy
	 * 
	 * het gevecht zelf. de beurten worden omstebeurt gedraaid totdat er iemand dood is!
	 */
	public void simuleer(Character character, String fileenemy, boolean leaveAfterLoose) throws FileNotFoundException, IOException, ClassNotFoundException {
		while ((hpNowME > 0) && (hpNowHE > 0)) {
			printOut(fileenemy);

			int lenME = 3 - (int) Math.log10(hpNowME / hpMaxME * 100);
			System.out.println("Mijn hp \t["
					+ hpStringME.substring(0, 22 + lenME)
					+ Math.round(hpNowME / hpMaxME * 100) + "%"
					+ hpStringME.substring(27, 50) + "]");

			int lenHE = 3 - (int) Math.log10(hpNowHE / hpMaxHE * 100);
			System.out.println("Zijn hp \t["
					+ hpStringHE.substring(0, 22 + lenHE)
					+ Math.round(hpNowHE / hpMaxHE * 100) + "%"
					+ hpStringHE.substring(27, 50) + "]");

			try {
				System.out.println("1: Aanvallen!");
				System.out.println("2: AdrenalineRush!");
				int i = scanner.nextInt();
				switch (i) {
				case 1:
					if (speedME >= speedHE) {
						fightME(fileenemy);
						if (hpNowHE <= 0)
							break;
						fightHE(fileenemy);
					} else {
						fightHE(fileenemy);
						if (hpNowHE <= 0)
							break;
						fightME(fileenemy);
					}
					break;

				case 2:
					if (adrenalineRush == true){
						hpNowME = (hpNowME + 25 > 0) ? hpMaxME : (getHpNowME() + 25);
						hpStringME = hpBalkmax.substring(0, (int) (50 * hpNowME / hpMaxME))
						+ hpBalkmin.substring(0,
								(50 - (int) (50 * hpNowME / hpMaxME)));
						setAdrenalineRush(false);

					}
					else {
						System.out.println("Al gebruikt in dit gevecht!");
					}
					break;
				}
			} catch (InputMismatchException e) {
				System.out.println("Geen geldige keuze");
				simuleer(character, fileenemy);
			}
		}

		if (hpNowHE == 0) {
			System.out.println("Yeeeeeeeeeuh! je hebt gewonnen!");
			Apl.boot.getCharacter().setHpNow(hpNowME);
		} else {
			System.out.println("Ah bagger, je verloor!");
			if (leaveAfterLoose)
				Apl.laden();
		}
	}
	
	public void simuleer(Character character, String fileenemy) throws FileNotFoundException, IOException, ClassNotFoundException {
		simuleer (character, fileenemy,true);
	}
	

	public double getHpNowME() {
		return this.hpNowME;
	}

	public void setAdrenalineRush(boolean adrenalineRush){
		this.adrenalineRush = adrenalineRush;
	}

	public void setHpMaxME(double hpMaxME) {
		this.hpMaxME = hpMaxME;
	}

	public void setHpNowME(double hpNowME) {
		this.hpNowME = hpNowME;
	}

	public void setArmourME(double armourME) {
		this.armourME = armourME;
	}

	public void setPowerME(double powerME) {
		this.powerME = powerME;
	}

	public void setHitratingME(double hitratingME) {
		this.hitratingME = hitratingME;
	}

	public void setDodgeratingME(double dodgeratingME) {
		this.dodgeratingME = dodgeratingME;
	}

	public void setSpeedME(int speedME) {
		this.speedME = speedME;
	}

	public void setCritChanceME(double critChanceME) {
		this.critChanceME = critChanceME;
	}

	public void setCritDamageME(double critDamageME) {
		this.critDamageME = critDamageME;
	}

	public void setHpMaxHE(double hpMaxHE) {
		this.hpMaxHE = hpMaxHE;
	}

	public void setHpNowHE(double hpNowHE) {
		this.hpNowHE = hpNowHE;
	}

	public void setArmourHE(double armourHE) {
		this.armourHE = armourHE;
	}

	public void setPowerHE(double powerHE) {
		this.powerHE = powerHE;
	}

	public void setHitratingHE(double hitratingHE) {
		this.hitratingHE = hitratingHE;
	}

	public void setDodgeratingHE(double dodgeratingHE) {
		this.dodgeratingHE = dodgeratingHE;
	}

	public void setSpeedHE(int speedHE) {
		this.speedHE = speedHE;
	}

	public void setCritChanceHE(double critChanceHE) {
		this.critChanceHE = critChanceHE;
	}

	public void setCritDamageHE(double critDamageHE) {
		this.critDamageHE = critDamageHE;
	}

}